Introduction

RNAseq data from:

Strenkert D, Schmollinger S, Gallaher SD, et al. Multiomics resolution of molecular events during a day in the life of Chlamydomonas. Proc Natl Acad Sci U S A. 2019;116(6):2374-2383.doi:10.1073/pnas.1815238116

Counts data normalisation and transformation with DESeq2

DESeq2:

Love MI, Huber W, Anders S (2014). “Moderated estimation of fold change and dispersion for RNA seq data with DESeq2.” Genome Biology, 15, 550. doi: 10.1186/s13059-014-0550-8

DESeq2 normalises the data according to library size (size factors) then uses a rlog transformation to diminish the impact of very low or very high expression genes on the subsequent analyses.

PCA of transformed counts data

PCA on rlog transformed count data.

PCA on rlog transformed count data.

PCA on rlog transformed count data.

PCA on rlog transformed count data.

On this Principal Component Analysis the cyclical nature of the experiment is apparent. From the time point 0h, the time points descend counter-clock wise, to return at the final 24h time point at the level of the first one. Note how time points at the end of the night (6h to 11h) are more closely related then the others, this is because Chlamydomonas cells are relatively quiescent at this part of their day cycle.

Hierarchical clustering of samples

Hierarchical clustering of rlog transformed count data.

Hierarchical clustering of rlog transformed count data.

The hierarchical clustering of the transformed data gives coherent clusters, grouping samples according to time periods. In this report I decided to use these clusters to separate the samples in the differential expression analysis.

Differential expression analysis with DESeq2

Here I use the previously defined clusters as formula to look for differentially expressed genes with DESeq2. However this can also be achieved by using directly the time conditions (as the R script in the workflow does).

## [1] "Total DEG in at least one time transition: 85.614094148011 %"

The use of time condition (as in the workflow R script) instead of the clusters gives less DEG, about 70%.

Rhythm analysis with DiscoRhythm

DiscoRhythm:

Matthew Carlucci, Algimantas Kriščiūnas, Haohan Li, Povilas Gibas, Karolis Koncevičius, Art Petronis, Gabriel Oh, DiscoRhythm: an easy-to-use web application and R package for discovering rhythmicity, Bioinformatics, Volume 36, Issue 6, 15 March 2020, Pages 1952–1954, https://doi.org/10.1093/bioinformatics/btz834

##       0                         2                        
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       4                         6                        
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       8                         10                       
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       10.5                      11                       
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       11.5                      12                       
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       14                        16                       
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       18                        20                       
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       22                        24                       
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"

The Lomb-Scargle qvalue distribution has a problematic profile, we will focus on Cosinor.

The acrophase is the time when the expression of the gene peaks. We will focus on the acrophase parameter instead of the amplitude of the expression signal to find putative regulators. Indeed, what we are interested in is not the intensity of gene expression, but rather the timing of expression.

Annotation

General view of rhythmic genes acrophases

Acrophases distribution.

Acrophases distribution.

c(paste0("Chloroplast", " (", nrow(final_data[final_data$simplified_subcellular_location == "Chloroplast",]), ")"),
  paste0("Chromosome", " (", nrow(final_data[final_data$simplified_subcellular_location == "Chromosome",]), ")"),
  paste0("Cilium", " (", nrow(final_data[final_data$simplified_subcellular_location == "Cilium",]), ")"),
  paste0("Cytoplasm", " (", nrow(final_data[final_data$simplified_subcellular_location == "Cytoplasm",]), ")"),
  paste0("Cytoskeleton", " (", nrow(final_data[final_data$simplified_subcellular_location == "Cytoskeleton",]), ")"),
  paste0("Endoplasmic reticulum", " (", nrow(final_data[final_data$simplified_subcellular_location == "Endoplasmic reticulum",]), ")"),
  paste0("Golgi apparatus", " (", nrow(final_data[final_data$simplified_subcellular_location == "Golgi apparatus",]), ")"),   
  paste0("Membrane", " (", nrow(final_data[final_data$simplified_subcellular_location == "Membrane",]), ")"),
  paste0("Mitochondrion", " (", nrow(final_data[final_data$simplified_subcellular_location == "Mitochondrion",]), ")"),
  paste0("Nucleus", " (", nrow(final_data[final_data$simplified_subcellular_location == "Nucleus",]), ")"),
  paste0("Other", " (", nrow(final_data[final_data$simplified_subcellular_location == "Other",]), ")"),
  paste0("unknown", " (", nrow(final_data[final_data$simplified_subcellular_location == "unknown",]), ")")) -> locations
   
#final_data2 <- filter(final_data, simplified_subcellular_location != "unknown")

ggplot(data = final_data, mapping = aes(x=CS.acrophase, fill=simplified_subcellular_location))+
    annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =0, ymax = Inf, alpha =0.3) +
    annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =0, ymax = Inf, alpha =0.3) +
    annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =0, ymax = Inf, alpha =0.3)+
    geom_histogram(aes(x = CS.acrophase, y = ..density..), binwidth = 0.3) +
    geom_line(stat = "density", alpha=0.5) +
    facet_wrap(~simplified_subcellular_location)+
    labs( x = "Acrophase", y = "Genes",
            title ="Acrophases distribution according to cellular location",
            subtitle = "Cosinor method")+
    scale_fill_discrete(name = "Cellular location", labels = locations)
Acrophases distribution.

Acrophases distribution.

Putative and known regulators

# Recovering some rhythmic OTAFs
opr <- final_data[ which(startsWith(final_data$gene_description, "OctotricoPeptide Repeat")) , ]                                                           
ppr <- final_data[ which(startsWith(final_data$gene_description, "PentatricoPeptide Repeat")) , ]
tpr <- final_data[ which(startsWith(final_data$gene_description, "TetratricoPeptide Repeat")) , ]

otaf <- union_all(opr, ppr)
otaf <- union_all(otaf, tpr)

# Adding expression data:
columns <- colnames(otaf)
otaf <- left_join(otaf, rlog_df)
colnames(otaf) <- make.unique(c(columns, rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)))

# Predicted chloroplast imported OTAFs
multi_otaf_chloro <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in otaf[which(otaf$subcellular_location == "Chloroplast"),]$gene_symbol){
    otaf[otaf$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
    tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
    tmp_df$gene <- prot
    multi_otaf_chloro <- rbind(multi_otaf_chloro, tmp_df)
}

multi_otaf_chloro <- multi_otaf_chloro[-1,]

# Predicted mitochondrion imported OTAFs
multi_otaf_mito <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in otaf[which(otaf$subcellular_location == "Mitochondrion"),]$gene_symbol){
    otaf[otaf$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
    tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
    tmp_df$gene <- prot
    multi_otaf_mito <- rbind(multi_otaf_mito, tmp_df)
}

multi_otaf_mito <- multi_otaf_mito[-1,]
Gene expression models.

Gene expression models.

Gene expression models.

Gene expression models.

Gene expression models.

Gene expression models.

Gene expression models.

Gene expression models.

To pair OTAFs and their putative organellar mRNA targets we must look at:

acro_day_chloro <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in chloro[which(chloro$CS.acrophase <15 & chloro$CS.acrophase >12 ),]$gene_symbol) {
    chloro[chloro$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
        tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
        tmp_df$gene <- prot
        acro_day_chloro <- rbind(acro_day_chloro, tmp_df)
}

acro_day_chloro <- acro_day_chloro[-1,]


otaf_chloro_acro_day <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <11 & otaf$CS.acrophase >8),]$gene_symbol){
    otaf[otaf$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
    tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
    tmp_df$gene <- prot
    otaf_chloro_acro_day <- rbind(otaf_chloro_acro_day, tmp_df)
}

otaf_chloro_acro_day <- otaf_chloro_acro_day[-1,]


# Plots 

ggplot(data = otaf_chloro_acro_day, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) + 
    annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =6, ymax = 13, alpha =0.3) +
    annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =6, ymax = 13, alpha =0.3) +
    annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =6, ymax = 13, alpha =0.3)+
    facet_wrap(~gene) +
    ylim(6, 13) +
    geom_smooth(method = "lm", se = FALSE, level = 0.95,
                formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
                fullrange = TRUE) +
    theme(legend.position = "none") +
    geom_point() +
    labs(y = "rlog(counts)", x = "Time (h)",
         title ="Chloroplast located OTAFs, acrophase at end of night",
         subtitle = "Cosinor method") +
    theme(plot.title = element_text(size = 11))+
    theme(strip.text.x = element_text(size = 11))
Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Here, we can identify known OTAF/chloroplast mRNA pairs/trios:

But also other potential OTAF/mRNA pairs!

References

Eberhard S, Loiselay C, Drapier D, Bujaldon S, Girard-Bascou J, Kuras R, Choquet Y, Wollman FA. Dual functions of the nucleus-encoded factor TDA1 in trapping and translation activation of atpA transcripts in Chlamydomonas reinhardtii chloroplasts. Plant J. 2011 Sep;67(6):1055-66. doi: 10.1111/j.1365-313X.2011.04657.x. Epub 2011 Jul 18. PMID: 21623973.

Wang F, Johnson X, Cavaiuolo M, Bohne AV, Nickelsen J, Vallon O. Two Chlamydomonas OPR proteins stabilize chloroplast mRNAs encoding small subunits of photosystem II and cytochrome b6 f. Plant J. 2015 Jun;82(5):861-73. doi: 10.1111/tpj.12858. PMID: 25898982.

Cline, S. G., Laughbaum, I. A. and Hamel, P. P. (2017) CCS2, an Octatricopeptide-Repeat Protein, Is Required for Plastid Cytochrome c Assembly in the Green Alga Chlamydomonas reinhardtii. Frontiers in plant science, 8, 1306. https://doi.org/10.3389/fpls.2017.01306

Viola S, Cavaiuolo M, Drapier D, et al. MDA1, a nucleus-encoded factor involved in the stabilization and processing of the atpA transcript in the chloroplast of Chlamydomonas. The Plant Journal: for Cell and Molecular Biology. 2019 Jun;98(6):1033-1047. DOI: 10.1111/tpj.14300.

Shin-Ichiro Ozawa, Marina Cavaiuolo, Domitille Jarrige, Richard Kuras, Mark Rutgers, Stephan Eberhard, Dominique Drapier, Francis-André Wollman, Yves Choquet, The OPR Protein MTHI1 Controls the Expression of Two Different Subunits of ATP Synthase CFo in Chlamydomonas reinhardtii, The Plant Cell, Volume 32, Issue 4, April 2020, Pages 1179–1203, https://doi.org/10.1105/tpc.19.00770

## R version 4.0.3 (2020-10-10)
## Platform: x86_64-conda-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
## 
## Matrix products: default
## BLAS/LAPACK: /shared/ifbstor1/software/miniconda/envs/r-4.0.3/lib/libopenblasp-r0.3.10.so
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] parallel  stats4    stats     graphics  grDevices utils     datasets 
## [8] methods   base     
## 
## other attached packages:
##  [1] gprofiler2_0.2.0            DiscoRhythm_1.6.0          
##  [3] pheatmap_1.0.12             ClassDiscovery_3.3.13      
##  [5] oompaBase_3.2.9             cluster_2.1.1              
##  [7] DESeq2_1.30.1               SummarizedExperiment_1.20.0
##  [9] Biobase_2.50.0              GenomicRanges_1.42.0       
## [11] GenomeInfoDb_1.26.7         IRanges_2.24.1             
## [13] S4Vectors_0.28.1            BiocGenerics_0.36.1        
## [15] MatrixGenerics_1.2.1        matrixStats_0.59.0         
## [17] data.table_1.14.0           forcats_0.5.1              
## [19] stringr_1.4.0               dplyr_1.0.6                
## [21] purrr_0.3.4                 readr_1.4.0                
## [23] tidyr_1.1.3                 tibble_3.1.2               
## [25] tidyverse_1.3.0             knitr_1.33                 
## [27] factoextra_1.0.7            ggplot2_3.3.4              
## [29] FactoMineR_2.4             
## 
## loaded via a namespace (and not attached):
##   [1] utf8_1.2.1             shinydashboard_0.7.1   tidyselect_1.1.1      
##   [4] heatmaply_1.2.1        RSQLite_2.2.7          AnnotationDbi_1.52.0  
##   [7] htmlwidgets_1.5.3      grid_4.0.3             TSP_1.1-10            
##  [10] BiocParallel_1.24.1    munsell_0.5.0          codetools_0.2-18      
##  [13] DT_0.17                miniUI_0.1.1.1         withr_2.4.2           
##  [16] colorspace_2.0-1       highr_0.9              gnm_1.1-1             
##  [19] rstudioapi_0.13        leaps_3.1              oompaData_3.1.1       
##  [22] ggsignif_0.6.1         labeling_0.4.2         GenomeInfoDbData_1.2.4
##  [25] farver_2.1.0           bit64_4.0.5            vctrs_0.3.8           
##  [28] generics_0.1.0         lambda.r_1.2.4         xfun_0.23             
##  [31] R6_2.5.0               seriation_1.2-9        locfit_1.5-9.4        
##  [34] bitops_1.0-7           cachem_1.0.5           DelayedArray_0.16.3   
##  [37] assertthat_0.2.1       promises_1.2.0.1       shinycssloaders_1.0.0 
##  [40] scales_1.1.1           nnet_7.3-15            ggExtra_0.9           
##  [43] gtable_0.3.0           MetaCycle_1.2.0        rlang_0.4.11          
##  [46] genefilter_1.72.1      systemfonts_1.0.1      scatterplot3d_0.3-41  
##  [49] splines_4.0.3          rstatix_0.7.0          lazyeval_0.2.2        
##  [52] shinyBS_0.61           broom_0.7.5            abind_1.4-5           
##  [55] BiocManager_1.30.10    yaml_2.2.1             reshape2_1.4.4        
##  [58] modelr_0.1.8           backports_1.2.1        httpuv_1.6.1          
##  [61] tools_4.0.3            ellipsis_0.3.2         kableExtra_1.3.4      
##  [64] jquerylib_0.1.4        RColorBrewer_1.1-2     Rcpp_1.0.6            
##  [67] plyr_1.8.6             zlibbioc_1.36.0        RCurl_1.98-1.3        
##  [70] ggpubr_0.4.0           viridis_0.6.1          haven_2.3.1           
##  [73] ggrepel_0.9.1          fs_1.5.0               magrittr_2.0.1        
##  [76] futile.options_1.0.1   magick_2.7.2           openxlsx_4.2.3        
##  [79] reprex_1.0.0           hms_1.1.0              shinyjs_2.0.0         
##  [82] mime_0.10              evaluate_0.14          xtable_1.8-4          
##  [85] XML_3.99-0.6           VennDiagram_1.6.20     rio_0.5.26            
##  [88] mclust_5.4.7           readxl_1.3.1           gridExtra_2.3         
##  [91] compiler_4.0.3         crayon_1.4.1           htmltools_0.5.1.1     
##  [94] mgcv_1.8-34            later_1.2.0            geneplotter_1.68.0    
##  [97] lubridate_1.7.10       DBI_1.1.1              formatR_1.9           
## [100] dbplyr_2.1.1           MASS_7.3-53.1          relimp_1.0-5          
## [103] BiocStyle_2.18.1       Matrix_1.3-4           car_3.0-10            
## [106] cli_2.5.0              pkgconfig_2.0.3        flashClust_1.01-2     
## [109] registry_0.5-1         foreign_0.8-81         plotly_4.9.3          
## [112] xml2_1.3.2             foreach_1.5.1          svglite_2.0.0         
## [115] annotate_1.68.0        bslib_0.2.5.1          webshot_0.5.2         
## [118] XVector_0.30.0         rvest_1.0.0            digest_0.6.27         
## [121] rmarkdown_2.8          cellranger_1.1.0       dendextend_1.14.0     
## [124] curl_4.3.1             shiny_1.6.0            nlme_3.1-152          
## [127] lifecycle_1.0.0        jsonlite_1.7.2         carData_3.0-4         
## [130] futile.logger_1.4.3    qvcalc_1.0.2           viridisLite_0.4.0     
## [133] fansi_0.5.0            pillar_1.6.1           lattice_0.20-41       
## [136] fastmap_1.1.0          httr_1.4.2             survival_3.2-10       
## [139] glue_1.4.2             zip_2.1.1              UpSetR_1.4.0          
## [142] iterators_1.0.13       bit_4.0.4              stringi_1.6.2         
## [145] sass_0.4.0             blob_1.2.1             memoise_2.0.0
LS0tCnRpdGxlOiAicmh5dGhtaWNfYW5hbHlzZXMuUm1kIgphdXRob3I6ICJEb21pdGlsbGUgSmFycmlnZSIKZGF0ZTogJ2ByIFN5cy5EYXRlKClgJwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHNlbGZfY29udGFpbmVkOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIGhpZ2hsaWdodDogemVuYnVybgogICAgdGhlbWU6IHlldGkKICAgIHRvYzogeWVzCiAgICBjb2RlX2ZvbGRpbmc6ICJoaWRlIgogIHBkZl9kb2N1bWVudDoKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIGhpZ2hsaWdodDogemVuYnVybgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFLCBlY2hvPUZBTFNFLCBldmFsPVRSVUV9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIGV2YWwgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUpCgpvcHRpb25zKHNjaXBlbiA9IDEyKSAjIyBNYXggbnVtYmVyIG9mIGRpZ2l0cyBmb3Igbm9uLXNjaWVudGlmaWMgbm90YXRpb24KYGBgCgpgYGB7ciB3b3JraW5nX2RpciwgaW5jbHVkZT1GQUxTRX0Kc2V0d2QoIi9zaGFyZWQvaWZic3RvcjEvcHJvamVjdHMvZHViaWkyMDIxL2RqYXJyaWdlL3Byb2pldF9zY2llbnRpZmlxdWUvc2NyaXB0cyIpCmBgYAoKYGBge3IgbGlicmFyaWVzLCBpbmNsdWRlPUZBTFNFfQpyZXF1aXJlZF9saWIgPC0gYygiRmFjdG9NaW5lUiIsCiAgICAgICAgICAgICAgICAgICJmYWN0b2V4dHJhIiwKICAgICAgICAgICAgICAgICAgImtuaXRyIiwKICAgICAgICAgICAgICAgICAgInRpZHl2ZXJzZSIsCiAgICAgICAgICAgICAgICAgICJkYXRhLnRhYmxlIiwKICAgICAgICAgICAgICAgICAgIlN1bW1hcml6ZWRFeHBlcmltZW50IiwKICAgICAgICAgICAgICAgICAgInRpYmJsZSIsCiAgICAgICAgICAgICAgICAgICJERVNlcTIiLAogICAgICAgICAgICAgICAgICAiZHBseXIiLAogICAgICAgICAgICAgICAgICAiQ2xhc3NEaXNjb3ZlcnkiLAogICAgICAgICAgICAgICAgICAicGhlYXRtYXAiKQoKcmVxdWlyZWRfYmlvYyA8LSBjKCJEaXNjb1JoeXRobSIsCiAgICAgICAgICAgICAgICAgICAiZ3Byb2ZpbGVyMiIpCgojIyMgQ1JBTiBsaWJyYXJpZXMgCmZvciAobGliIGluIHJlcXVpcmVkX2xpYikgewogICAgaWYgKCFyZXF1aXJlKGxpYiwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgewogICAgICAgIGluc3RhbGwucGFja2FnZXMobGliKQogICAgfQogICAgcmVxdWlyZShsaWIsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKfQoKCiMjIyBCaW9jbWFuYWdlciBsaWJyYXJpZXMgCgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkJpb2NNYW5hZ2VyIiwgcXVpZXRseT1UUlVFKSkKICAgIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIikKCmZvciAobGliIGluIHJlcXVpcmVkX2Jpb2MpewogICAgaWYgKCFyZXF1aXJlKGxpYiwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgewogICAgICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKGxpYiwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKQogICAgfQogICAgcmVxdWlyZShsaWIsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKfQoKCmBgYAoKIyMgSW50cm9kdWN0aW9uCgojIyMjIFJOQXNlcSBkYXRhIGZyb206CgoqKlN0cmVua2VydCBELCBTY2htb2xsaW5nZXIgUywgR2FsbGFoZXIgU0QsIGV0IGFsLiBNdWx0aW9taWNzIHJlc29sdXRpb24gb2YgbW9sZWN1bGFyIGV2ZW50cyBkdXJpbmcgYSBkYXkgaW4gdGhlIGxpZmUgb2YgQ2hsYW15ZG9tb25hcy4gUHJvYyBOYXRsIEFjYWQgU2NpIFUgUyBBLiAyMDE5OzExNig2KToyMzc0LTIzODMuW2RvaToxMC4xMDczL3BuYXMuMTgxNTIzODExNl0oaHR0cHM6Ly93d3cucG5hcy5vcmcvY29udGVudC8xMTYvNi8yMzc0KSoqCgoKIyMjIyBGbG93IGNoYXJ0IG9mIG15IHByb2plY3QgUk5Bc2VxIGFuYWx5c2lzIHBhcnQ6CiFbbXkgUk5Bc2VxIHdvcmtmbG93XShmbG93X2NoYXJ0X1JOQV9naXRodWJfdmVyLnBuZykKCgpBZnRlciB0cmVhdGluZyB0aGUgcmF3IFJOQXNlcSBkYXRhIHdpdGggbXkgYHJuYV93b3JrZmxvdy5zbWtgLCBJIG9idGFpbmVkIGEgY291bnRzIHRhYmxlIHdpdGggZWFjaCBSTkFzZXEgbGlicmFyeSwgZm9sbG93aW5nIHRoZSB0aW1lIHNlcmllcyBvcmRlci4KCkluIHRoaXMgUiBtYXJrZG93biByZXBvcnQsIEkgIHBlcmZvcm0gYSBzaG9ydCBhbmFseXNpcyBvZiB0aGlzIGRhdGEgYW5kIGV4dHJhY3QgaW5mb3JtYXRpb24gb24gc29tZSBwb3RlbnRpYWwgb3Iga25vd24gT3JnYW5lbGxhciBUcmFucy1BY3RpbmcgRmFjdG9ycyAoT1RBRnMpIG9mIF9DaGxhbXlkb21vbmFzIHJlaW5oYXJkdGlpXy4KCmBgYHtyIGRhdGFfbG9hZGluZ19hbmRfcHJlcGFyYXRpb259CgojIyBMb2FkaW5nIGNvdW50cyBkYXRhIGFuZCBtZXRhZGF0YQptZXRhX3RlbXAgPC0gcmVhZC5jc3YoIi4uL2RhdGEvc2FtcGxlX0Rpc2NvUnl0aG1fZm9ybWF0LnRzdiIsIHNlcD0iXHQiKQpjb3VudHNfcnVuZF9kZiA8LSByZWFkLmNzdigiLi4vcmVzdWx0cy9tYXBwaW5nL2Z1bGxfZGF0YS90b3RhbF9jb3VudHNfaW50LmNzdiIsIHNlcD0iXHQiLCByb3cubmFtZXMgPSAxKQoKIyMgUGlja2luZyBjb2xvcnMgZm9yIHRpbWVwb2ludHMKbWV0YV90ZW1wJGNvbG9yIDwtIGMocmVwKCIjMDAwZjNiIiwgMyksIHJlcCgiIzAwMTQ0ZSIsIDMpLCByZXAoIiMwMDE5NjIiLCAzKSwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCIjMDAxMTYyIiwgMyksIHJlcCgiIzAwMTc4OSIsIDMpLCByZXAoIiMwMDFlYjEiLCAzKSwKICAgICAgICAgICAgICAgICAgICByZXAoIiMxNDNiZmYiLCAzKSwgcmVwKCIjODZiY2Y5IiwgMyksIHJlcCgiI2ZmYzU3NiIsIDMpLCAKICAgICAgICAgICAgICAgICAgICByZXAoIiNmZmQ0MDAiLCAzKSwgcmVwKCIjZmZlOTAwIiwgMyksIHJlcCgiI2ZmZjA0ZSIsIDMpLAogICAgICAgICAgICAgICAgICAgIHJlcCgiI2ZmZjU4OSIsIDMpLCByZXAoIiNjZWMwMzEiLCAzKSwgcmVwKCIjZmZiZjAwIiwgMyksCiAgICAgICAgICAgICAgICAgICAgcmVwKCIjMDAxMTYyIiwgMykpCgojIyBMb2FkaW5nIGFubm90YXRpb24gZGF0YQphbm5vdGF0aW9ucyA8LSByZWFkLmNzdigiLi4vZGF0YS9waHl0b3pvbWUvQ3JlaW5oYXJkdGlpL3Y1LjYvYW5ub3RhdGlvbi9nZW5lX2Fubm90YXRpb24udHN2IiwKICAgICAgICAgICAgICAgICAgICAgICAgc2VwPSJcdCIpCmFubm90YXRpb25zX29yZ2FuZWxsZXMgPC0gcmVhZC5jc3YoIi4uL2RhdGEvcGh5dG96b21lL0NyZWluaGFyZHRpaS92NS42L2Fubm90YXRpb24vb3JnYW5lbGxlc19hbm5vdGF0aW9uLnRzdiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwPSJcdCIpCgojIC8hXCBSZW1vdmluZyBkdXBsaWNhdGVkIGdlbmVzCmFubm90YXRpb25zJGdlbmVfaWQgIDwtIG1ha2UudW5pcXVlKGFubm90YXRpb25zJGdlbmVfaWQsIHNlcD0iLiIpCgoKIyMgTWF0cml4IGNvbnZlcnNpb24KbWF0cml4X2NvdW50c19ERVNlcTIgPC0gYXMubWF0cml4KGNvdW50c19ydW5kX2RmWywyOjQ5XSkgCnJvd25hbWVzKG1hdHJpeF9jb3VudHNfREVTZXEyKSA8LSBjb3VudHNfcnVuZF9kZlssMV0KCmBgYAoKIyMgQ291bnRzIGRhdGEgbm9ybWFsaXNhdGlvbiBhbmQgdHJhbnNmb3JtYXRpb24gd2l0aCBERVNlcTIKCioqREVTZXEyOioqIAoKTG92ZSBNSSwgSHViZXIgVywgQW5kZXJzIFMgKDIwMTQpLiAiTW9kZXJhdGVkIGVzdGltYXRpb24gb2YgZm9sZCBjaGFuZ2UgYW5kIGRpc3BlcnNpb24gZm9yIFJOQSBzZXEgZGF0YSB3aXRoIERFU2VxMi4iIF9HZW5vbWUgQmlvbG9neV8sIDE1LCA1NTAuIGRvaTogMTAuMTE4Ni9zMTMwNTktMDE0LTA1NTAtOAoKYGBge3IgZGF0YV9ub3JtYWxpc2F0aW9uX3dpdGhfREVTZXEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyMjIyBOb3JtYWxpc2F0aW9uIGFuZCB0cmFuc2Zvcm1hdGlvbiBvZiBjb3VudCBkYXRhIHdpdGggREVTZXEyICMjIyMKZGRzRnVsbCA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IG1hdHJpeF9jb3VudHNfREVTZXEyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbERhdGEgPSBtZXRhX3RlbXAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduID0gfiB0aW1lKQoKIyMgU2l6ZSBmYWN0b3JzCmRkc0Z1bGwgPC0gZXN0aW1hdGVTaXplRmFjdG9ycyhkZHNGdWxsKQoKIyMgVGFraW5nIG91dCB1bmV4cHJlc3NlZCBnZW5lcwpkZHNGdWxsIDwtIGRkc0Z1bGxbIHJvd1N1bXMoY291bnRzKGRkc0Z1bGwpKSA+IDAsIF0KCiMjIHJsb2cgdHJhbnNmb3JtYXRpb24KcmxvZ19kYXRhIDwtIHJsb2coZGRzRnVsbCwgYmxpbmQ9VFJVRSkKYm94cGxvdChjb3VudHMoZGRzRnVsbCwgbm9ybWFsaXplZD1GQUxTRSksCiAgICAgICAgY29sID0gbWV0YV90ZW1wJGNvbG9yLAogICAgICAgIGhvcml6b250YWwgPSBUUlVFLCAKICAgICAgICBsYXMgPSAxLAogICAgICAgIGNleC5heGlzID0gMC40NSwKICAgICAgICBjZXggPSAwLjUsCiAgICAgICAgeGxhYiA9ICJyYXcgdmFsdWUiLAogICAgICAgIG1haW49IkJveHBsb3RzIG9mIHVudHJhbnNmb3JtZWQgCmdlbmUgY291bnRzIikKCmJveHBsb3QoYXNzYXkocmxvZ19kYXRhKSwKICAgICAgICBjb2wgPSBtZXRhX3RlbXAkY29sb3IsCiAgICAgICAgaG9yaXpvbnRhbCA9IFRSVUUsIAogICAgICAgIGxhcyA9IDEsCiAgICAgICAgY2V4LmF4aXMgPSAwLjQ1LAogICAgICAgIGNleCA9IDAuNSwKICAgICAgICB4bGFiID0gInJsb2codmFsdWUpIiwKICAgICAgICBtYWluPSJCb3hwbG90cyBvZiBybG9nIHRyYW5zZm9ybWVkIApnZW5lIGNvdW50cyIpCgoKIyMgVHJhbnNmb3JtYXRpb24gdmlzdWFsaXNhdGlvbgpwYXIobWZyb3c9YygxLDIpKQpwbG90KGNvdW50cyhkZHNGdWxsLCBub3JtYWxpemVkPUZBTFNFKVssMTE6MTJdLApwY2g9MTYsIGNleD0wLjMsIHhsaW09YygwLDIwZTMpLCB5bGltPWMoMCwyMGUzKSwgbWFpbj0icmF3IGNvdW50cyIpCgpwbG90KGFzc2F5KHJsb2dfZGF0YSlbLDExOjEyXSwKcGNoPTE2LCBjZXg9MC4zLCBtYWluPSJybG9nIG5vcm1hbGl6ZWQgY291bnRzIikKcGFyKG1mcm93PWMoMSwxKSkKCmBgYAoKREVTZXEyIG5vcm1hbGlzZXMgdGhlIGRhdGEgYWNjb3JkaW5nIHRvIGxpYnJhcnkgc2l6ZSAoc2l6ZSBmYWN0b3JzKSB0aGVuIHVzZXMgYSBybG9nIHRyYW5zZm9ybWF0aW9uIHRvIGRpbWluaXNoIHRoZSBpbXBhY3Qgb2YgdmVyeSBsb3cgb3IgdmVyeSBoaWdoIGV4cHJlc3Npb24gZ2VuZXMgb24gdGhlIHN1YnNlcXVlbnQgYW5hbHlzZXMuIAoKIyMgUENBIG9mIHRyYW5zZm9ybWVkIGNvdW50cyBkYXRhCgpgYGB7ciBQQ0FfcmxvZ19kYXRhLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjkwJSIsIGZpZy5jYXA9IlBDQSBvbiBybG9nIHRyYW5zZm9ybWVkIGNvdW50IGRhdGEuIn0KIyMgcmxvZyB0cmFuc2Zvcm1lZCBkYXRhLCBQQ0EKCiMjIGV4dHJhY3QgcmxvZyBtYXRyaXgKY291bnRzX3Jsb2cgPC0gYXNzYXkocmxvZ19kYXRhKQoKIyMgUnVuIFBDQQpyZXNfcGNhIDwtIFBDQSh0KGNvdW50c19ybG9nKSwgZ3JhcGg9RkFMU0UpCgojIyBHcmFwaHMKZnZpel9laWcocmVzX3BjYSwgdGl0bGU9IlBDQSBvZiBybG9nIGRhdGEsIEVpZ2VuIHZhbHVlcyIsIGFkZGxhYmVscyA9IFRSVUUsIHlsaW0gPSBjKDAsIDUwKSkKCmZ2aXpfcGNhX2luZChyZXNfcGNhLCBsYWJlbD0ibm9uZSIsCiAgICAgICAgICAgICB0aXRsZT0iUENBIG9mIHJsb2cgZGF0YSIsCiAgICAgICAgICAgICBoYWJpbGxhZ2U9YXMuZmFjdG9yKG1ldGFfdGVtcCR0aW1lKSwKICAgICAgICAgICAgIG1lYW4ucG9pbnQ9RkFMU0UsCiAgICAgICAgICAgICBwb2ludHNoYXBlID0gMTkpIApgYGAKCk9uIHRoaXMgUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcyB0aGUgY3ljbGljYWwgbmF0dXJlIG9mIHRoZSBleHBlcmltZW50IGlzIGFwcGFyZW50LiBGcm9tIHRoZSB0aW1lIHBvaW50IDBoLCB0aGUgdGltZSBwb2ludHMgZGVzY2VuZCBjb3VudGVyLWNsb2NrIHdpc2UsIHRvIHJldHVybiBhdCB0aGUgZmluYWwgMjRoIHRpbWUgcG9pbnQgYXQgdGhlIGxldmVsIG9mIHRoZSBmaXJzdCBvbmUuIE5vdGUgaG93IHRpbWUgcG9pbnRzIGF0IHRoZSBlbmQgb2YgdGhlIG5pZ2h0ICg2aCB0byAxMWgpIGFyZSBtb3JlIGNsb3NlbHkgcmVsYXRlZCB0aGVuIHRoZSBvdGhlcnMsIHRoaXMgaXMgYmVjYXVzZSBfQ2hsYW15ZG9tb25hc18gY2VsbHMgYXJlIHJlbGF0aXZlbHkgcXVpZXNjZW50IGF0IHRoaXMgcGFydCBvZiB0aGVpciBkYXkgY3ljbGUuCgojIyBIaWVyYXJjaGljYWwgY2x1c3RlcmluZyBvZiBzYW1wbGVzCgpgYGB7ciBoaWVyYXJjaGljYWxfY2x1c3RlcmluZywgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSI5MCUiLCBmaWcuY2FwPSJIaWVyYXJjaGljYWwgY2x1c3RlcmluZyBvZiBybG9nIHRyYW5zZm9ybWVkIGNvdW50IGRhdGEuIn0KCmRpc3RzIDwtIGRpc3QodChhc3NheShybG9nX2RhdGEpKSkKcGFyKG1mcm93PWMoMSwxKSkKdHJlZV9ybG9nIDwtIGhjbHVzdChkaXN0cykKCm15X2NvbG9ycyA9IGMoIiNmZmM1NzYiLCAiIzQ0NWNkNyIsICIjZmZmMDRlIiwgIiMwMDE3ODkiLCAiI2ZhZjVjNiIpCgpwYXIoYmcgPSAiZGFya2dyZXkiLCBtZnJvdz1jKDEsIDEpKQpwbG90Q29sb3JlZENsdXN0ZXJzKHRyZWVfcmxvZywgbGFicyA9IG1ldGFfdGVtcCR0aW1lLAogICAgICAgICAgICAgICAgICAgIHlsYWIgPSBOQSwgeGxhYiA9IE5BLCBjZXggPSAsIGxhcyA9IDEsCiAgICAgICAgICAgICAgICAgICAgY29scyA9IG1ldGFfdGVtcCRjb2xvciwgY29sID0gIndoaXRlIiwKICAgICAgICAgICAgICAgICAgICBtYWluID0gIlNhbXBsZXMgRXVjbGlkaWFuIGRpc3RhbmNlIGhpZXJhcmNoaWNhbCAKY2x1c3RlcmluZywgcmxvZywgY29tcGxldGUgbGlua2FnZSIpCnJlY3QuaGNsdXN0KHRyZWVfcmxvZywgaz01LCBib3JkZXI9bXlfY29sb3JzKQpwYXIoYmc9IndoaXRlIikKCgojIFNhdmluZyBjbHVzdGVycwpjbHVzdGVyc19uYW1lcyA8LSBjKCJlYXJseV9uaWdodCIsCiAgICAgICAgICAgICAgICAgICAgIm5pZ2h0IiwKICAgICAgICAgICAgICAgICAgICAiZGF3biIsCiAgICAgICAgICAgICAgICAgICAgImRheSIsCiAgICAgICAgICAgICAgICAgICAgImR1c2siKQpjbHVzdGVyc19ybG9nIDwtIGN1dHJlZSh0cmVlX3Jsb2csIGs9NSkKbWV0YV90ZW1wJGNsdXN0ZXIgPC0gY2x1c3RlcnNfbmFtZXNbY2x1c3RlcnNfcmxvZ10KCmBgYAoKVGhlIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nIG9mIHRoZSB0cmFuc2Zvcm1lZCBkYXRhIGdpdmVzIGNvaGVyZW50IGNsdXN0ZXJzLCBncm91cGluZyBzYW1wbGVzIGFjY29yZGluZyB0byB0aW1lIHBlcmlvZHMuIEluIHRoaXMgcmVwb3J0IEkgZGVjaWRlZCB0byB1c2UgdGhlc2UgY2x1c3RlcnMgdG8gc2VwYXJhdGUgdGhlIHNhbXBsZXMgaW4gdGhlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzLgoKCiMjIERpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIHdpdGggREVTZXEyCkhlcmUgSSB1c2UgdGhlIHByZXZpb3VzbHkgZGVmaW5lZCBjbHVzdGVycyBhcyBmb3JtdWxhIHRvIGxvb2sgZm9yIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyB3aXRoIERFU2VxMi4gSG93ZXZlciB0aGlzIGNhbiBhbHNvIGJlIGFjaGlldmVkIGJ5IHVzaW5nIGRpcmVjdGx5IHRoZSB0aW1lIGNvbmRpdGlvbnMgKGFzIHRoZSBSIHNjcmlwdCBpbiB0aGUgd29ya2Zsb3cgZG9lcykuIAoKYGBge3IgREVHLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIyMjIERFU2VxMiBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyBieSB0aW1lIHBvaW50ICMjIyMKZGRzVGltZXMgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGEgPSBtYXRyaXhfY291bnRzX0RFU2VxMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IG1ldGFfdGVtcCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduID0gfiBjbHVzdGVyKSAjIH4gdGltZV9mYWN0b3IgY291bGQgYmUgdXNlZCBpbnN0ZWFkCgojIyBFbGltaW5hdGlvbiBvZiBsb3dseSBleHByZXNzZWQgZ2VuZXMKCmRkc1RpbWVzIDwtIGRkc1RpbWVzWyByb3dTdW1zKGNvdW50cyhkZHNUaW1lcykpID4gNjAsIF0KCiMjIERpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzCmRkc1RpbWVzIDwtIERFU2VxKGRkc1RpbWVzKQp0aW1lX3BvaW50cyA8LSB1bmlxdWUobWV0YV90ZW1wJGNsdXN0ZXIpICMgdGltZV9mYWN0b3IgY291bGQgYmUgdXNlZCBpbnN0ZWFkCgp0aW1lX3JlcCA8LSBjKHJlcCh0aW1lX3BvaW50cywgYygxLCByZXAoMiwgbGVuZ3RoKHRpbWVfcG9pbnRzKS0xKSkpLCB0aW1lX3BvaW50c1sxXSkKcGFpcnMgPC0gbWF0cml4KGFzLmZhY3Rvcih0aW1lX3JlcCksIG5jb2wgPSAyLCBieXJvdyA9IFRSVUUpCgoKIyBTaWduaWZpY2FudCBnZW5lcyBpbml0aWFsaXNhdGlvbgpzaWduaWZpY2FudF9nZW5lcyA8LSBjKCkKCiMgRXh0cmFjdGlvbiBvZiBERVNlcTIgcmVzdWx0cwpmb3IgKGkgaW4gKDEgOiBucm93KHBhaXJzKSkpIHsKICAgIGVsZSA8LSBwYWlyc1tpLF0KICAgIHRleHQgPC0gcGFzdGUwKGVsZVsxXSwgIi8iLCBlbGVbMl0sICIgREVHOiIpCiAgICByZXNERVNlcSA8LSByZXN1bHRzKGRkc1RpbWVzLCBjb250cmFzdCA9IGMoImNsdXN0ZXIiLCBlbGVbMV0sIGVsZVsyXSksICMgInRpbWVfZmFjdG9yIiBjb3VsZCBiZSB1c2VkIGluc3RlYWQKICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXBlbmRlbnRGaWx0ZXJpbmcgPSBUUlVFLCBhbHBoYT0wLjAxKQogICAgbWVzc2FnZSh0ZXh0KQogICAgbWVzc2FnZSggc3VtKCByZXNERVNlcSRwYWRqIDwgMC4wMSwgbmEucm09VFJVRSApICkKICAgIHRlbXBfbGlzdCA8LSByb3cubmFtZXMocmVzREVTZXFbd2hpY2gocmVzREVTZXEkcGFkaiA8IDAuMDEpLF0pCiAgICBtZXNzYWdlKHBhc3RlMChjKGxlbmd0aCh0ZW1wX2xpc3QpL25yb3coY291bnRzX3J1bmRfZGYpICogMTAwKSwgIiAlIikpCiAgICBzaWduaWZpY2FudF9nZW5lcyA8LSB1bmlvbih0ZW1wX2xpc3QsIHNpZ25pZmljYW50X2dlbmVzKQp9CgpwcmludChwYXN0ZTAoIlRvdGFsIERFRyBpbiBhdCBsZWFzdCBvbmUgdGltZSB0cmFuc2l0aW9uOiAiLCAobGVuZ3RoKHNpZ25pZmljYW50X2dlbmVzKS9ucm93KGNvdW50c19ydW5kX2RmKSAqIDEwMCksICIgJSIpKQoKc2lnbl9kZiA8LSBkYXRhLmZyYW1lKHJvdy5uYW1lcyA9IHNpZ25pZmljYW50X2dlbmVzKQpzaWduX2RmJGRpZmZfZXhwciA8LSAieWVzIgpzaWduX2RmJGdlbmVfaWQgPC0gcm93Lm5hbWVzKHNpZ25fZGYpCgoKYGBgClRoZSB1c2Ugb2YgdGltZSBjb25kaXRpb24gKGFzIGluIHRoZSB3b3JrZmxvdyBSIHNjcmlwdCkgaW5zdGVhZCBvZiB0aGUgY2x1c3RlcnMgZ2l2ZXMgbGVzcyBERUcsIGFib3V0IDcwJS4KCiMjIFJoeXRobSBhbmFseXNpcyB3aXRoIERpc2NvUmh5dGhtCgoqKkRpc2NvUmh5dGhtOioqCgpNYXR0aGV3IENhcmx1Y2NpLCBBbGdpbWFudGFzIEtyacWhxI1pxatuYXMsIEhhb2hhbiBMaSwgUG92aWxhcyBHaWJhcywgS2Fyb2xpcyBLb25jZXZpxI1pdXMsIEFydCBQZXRyb25pcywgR2FicmllbCBPaCwgRGlzY29SaHl0aG06IGFuIGVhc3ktdG8tdXNlIHdlYiBhcHBsaWNhdGlvbiBhbmQgUiBwYWNrYWdlIGZvciBkaXNjb3ZlcmluZyByaHl0aG1pY2l0eSwgX0Jpb2luZm9ybWF0aWNzXywgVm9sdW1lIDM2LCBJc3N1ZSA2LCAxNSBNYXJjaCAyMDIwLCBQYWdlcyAxOTUy4oCTMTk1NCwgaHR0cHM6Ly9kb2kub3JnLzEwLjEwOTMvYmlvaW5mb3JtYXRpY3MvYnR6ODM0CgpgYGB7ciByaHl0aG1fYW5hbHlzaXNfRGlzY29SaHl0aG19CgojIENvbnZlcnRpbmcgcmxvZyBtYXRyaXggaW4gU0UgKFN1Ym1hcmlzZWQgRXhwZXJpbWVudCkpCmdlbmVfaWQgPC0gcm93Lm5hbWVzKGNvdW50c19ybG9nKQpybG9nX2RmIDwtIGFzLmRhdGEuZnJhbWUoY291bnRzX3Jsb2cpCnJsb2dfZGYgPC0gYWRkX2NvbHVtbihybG9nX2RmLCBnZW5lX2lkLCAuYmVmb3JlPTEpCmlucHV0X2RhdGEgPC0gZGlzY29ERnRvU0UocmxvZ19kZikKCmRpc2NvRGVzaWduU3VtbWFyeShpbnB1dF9kYXRhKQoKIyBPdXIgdGltZXBvaW50cyBhcmUgbm90IGVxdWlkaXN0YW50LCB3ZSBjYW4gdXNlIGVpdGhlciB0aGUgY29zaW5vciBvciBMb21iLVNjYXJnbGUgbWV0aG9kIHRvIGRldGVjdCBmZWF0dXJlIHJoeXRobXMKCiMgQ29zaW5vcgpyeXRobXNfZ2VuZXNfQ1MgPC0gZGlzY29PREFzKGlucHV0X2RhdGEsIHBlcmlvZCA9IDI0LCBtZXRob2QgPSAiQ1MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpcmN1bGFyX3QgPSBUUlVFLCBuY29yZXMgPSA0KQoKIyBMb21iLVNjYXJnbGUKcnl0aG1zX2dlbmVzX0xTIDwtIGRpc2NvT0RBcyhpbnB1dF9kYXRhLCBwZXJpb2QgPSAyNCwgbWV0aG9kID0gIkxTIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2lyY3VsYXJfdCA9IFRSVUUsIG5jb3JlcyA9IDQpCgoKcGFyKG1mcm93PWMoMSwyKSkKaGlzdChkYXRhLmZyYW1lKHJ5dGhtc19nZW5lc19DUykkQ1MucXZhbHVlLCBicmVha3MgPSAxMDAsIAogICAgIG1haW4gPSAicXZhbHVlIGNvc2lub3IiLAogICAgIHhsYWIgPSAicXZhbHVlIikKaGlzdChkYXRhLmZyYW1lKHJ5dGhtc19nZW5lc19MUykkTFMucXZhbHVlLCBicmVha3MgPSAxMDAsIAogICAgIG1haW4gPSAicXZhbHVlIExvbWItU2NhcmdsZSIsCiAgICAgeGxhYiA9ICJxdmFsdWUiKQpgYGAKClRoZSBMb21iLVNjYXJnbGUgcXZhbHVlIGRpc3RyaWJ1dGlvbiBoYXMgYSBwcm9ibGVtYXRpYyBwcm9maWxlLCB3ZSB3aWxsIGZvY3VzIG9uIENvc2lub3IuCgpgYGB7ciBjb3Npbm9yX3JoeXRobWljX2dlbmVzfQojIEV4dHJhY3RpbmcganVzdCB0aGUgZGF0YWZyYW1lcyBmcm9tIHRoZSBkaXNjb3J5dGhtIG91dHB1dApDU19kZiA8LSBkYXRhLmZyYW1lKHJ5dGhtc19nZW5lc19DUykKCgojIFJldHJlaXZpbmcgb25seSBtb3N0IHNpZ25pZmljYW50IGdlbmVzIAojIHF2YWx1ZSBpbmZlcmlvciB0byAwLjA1CkNTX2RmIDwtIENTX2RmW0NTX2RmJENTLnF2YWx1ZSA8IDAuMDUsXQoKCnBhcihtZnJvdz1jKDEsMikpCmhpc3QoQ1NfZGYkQ1MuYW1wbGl0dWRlLCBicmVha3MgPSAxMDAsIAogICAgIG1haW4gPSAiYW1wbGl0dWRlcyBjb3Npbm9yIAphZnRlciBzZWxlY3Rpb24iLAogICAgIHhsYWIgPSAiYW1wbGl0dWRlIikKCmhpc3QoQ1NfZGYkQ1MuYWNyb3BoYXNlLCBicmVha3MgPSAxMDAsIAogICAgIG1haW4gPSAiYWNyb3BoYXNlcyBjb3Npbm9yIAphZnRlciBzZWxlY3Rpb24iLAogICAgIHhsYWIgPSAiaG91ciIpCnBhcihtZnJvdz1jKDEsMSkpCgpgYGAKClRoZSBhY3JvcGhhc2UgaXMgdGhlIHRpbWUgd2hlbiB0aGUgZXhwcmVzc2lvbiBvZiB0aGUgZ2VuZSBwZWFrcy4gV2Ugd2lsbCBmb2N1cyBvbiB0aGUgYWNyb3BoYXNlIHBhcmFtZXRlciBpbnN0ZWFkIG9mIHRoZSBhbXBsaXR1ZGUgb2YgdGhlIGV4cHJlc3Npb24gc2lnbmFsIHRvIGZpbmQgcHV0YXRpdmUgcmVndWxhdG9ycy4gSW5kZWVkLCB3aGF0IHdlIGFyZSBpbnRlcmVzdGVkIGluIGlzIG5vdCB0aGUgaW50ZW5zaXR5IG9mIGdlbmUgZXhwcmVzc2lvbiwgYnV0IHJhdGhlciB0aGUgdGltaW5nIG9mIGV4cHJlc3Npb24uCgojIyBBbm5vdGF0aW9uCgpgYGB7ciBhbm5vdGF0aW9uX29mX2RhdGF9CgojIyBFeHRyYWN0aW9uIG9mIGFubm90YXRpb25zCnJvd19DUyA8LSByb3cubmFtZXMoQ1NfZGYpCgpDU19kZiRnZW5lX2lkIDwtIHJvd19DUwoKQ1NfZGYgPC0gbGVmdF9qb2luKENTX2RmLCBhbm5vdGF0aW9ucykKCmlkX29yZ2FuZWxsZSA9IGFubm90YXRpb25zX29yZ2FuZWxsZXMkZ2VuZV9pZApyb3cubmFtZXMoYW5ub3RhdGlvbnNfb3JnYW5lbGxlcykgPC0gaWRfb3JnYW5lbGxlCgpyb3dfQ1MgLT4gcm93Lm5hbWVzKENTX2RmKQoKCmZvciAoaWQgaW4gaWRfb3JnYW5lbGxlKSB7CiAgICBDU19kZltpZCwgImdlbmVfc3ltYm9sIl0gPC0gYW5ub3RhdGlvbnNfb3JnYW5lbGxlc1tpZCwiZ2VuZV9zeW1ib2wiXQp9CgoKQ1NfZGYkZ2VuZV9pZCA8LSByb3cubmFtZXMoQ1NfZGYpCgpDU19kZiRlbmNvZGVkIDwtICJOdWNsZXVzIgoKQ1NfZGZbd2hpY2goc3RhcnRzV2l0aChDU19kZiRnZW5lX2lkLCAiQ3JlTXQuIikpLCAiZW5jb2RlZCJdIDwtICJNaXRvY2hvbmRyaW9uIgpDU19kZlt3aGljaChzdGFydHNXaXRoKENTX2RmJGdlbmVfaWQsICJDcmVDcC4iKSksICJlbmNvZGVkIl0gPC0gIkNobG9yb3BsYXN0IgpDU19kZlt3aGljaChzdGFydHNXaXRoKENTX2RmJGdlbmVfaWQsICJDcmVNdC4iKSksICJzdWJjZWxsdWxhcl9sb2NhdGlvbiJdIDwtICJNaXRvY2hvbmRyaW9uIgpDU19kZlt3aGljaChzdGFydHNXaXRoKENTX2RmJGdlbmVfaWQsICJDcmVDcC4iKSksICJzdWJjZWxsdWxhcl9sb2NhdGlvbiJdIDwtICJDaGxvcm9wbGFzdCIKQ1NfZGZbd2hpY2goc3RhcnRzV2l0aChDU19kZiRnZW5lX2lkLCAiQ3JlTXQuIikpLCAic2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiJdIDwtICJNaXRvY2hvbmRyaW9uIgpDU19kZlt3aGljaChzdGFydHNXaXRoKENTX2RmJGdlbmVfaWQsICJDcmVDcC4iKSksICJzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uIl0gPC0gIkNobG9yb3BsYXN0IgoKQ1NfZGZbd2hpY2goc3RhcnRzV2l0aChDU19kZiRnZW5lX2Rlc2NyaXB0aW9uLCAiT2N0b3RyaWNvUGVwdGlkZSIpID09IFRSVUUpLCBdIC0+IENTX3N1YnNldF9vcHIKQ1NfZGZbd2hpY2goc3RhcnRzV2l0aChDU19kZiRnZW5lX2Rlc2NyaXB0aW9uLCAiUGVudGF0cmljb1BlcHRpZGUiKSA9PSBUUlVFKSwgXSAtPiBDU19zdWJzZXRfcHByCgoKIyBHZW5lcyBib3RoIHJoeXRobWljIGFuZCBERQpmaW5hbF9kYXRhIDwtIGxlZnRfam9pbihDU19kZiwgc2lnbl9kZiwgYnkgPSAiZ2VuZV9pZCIpCmZpbmFsX2RhdGEgPC0gZmluYWxfZGF0YVt3aGljaChmaW5hbF9kYXRhJGRpZmZfZXhwciA9PSAieWVzIiksXQpmaW5hbF9kYXRhIDwtIGZpbmFsX2RhdGFbIHdoaWNoKCFpcy5uYShmaW5hbF9kYXRhJENTLmFjcm9waGFzZSkpICwgXQoKYGBgCgojIyBHZW5lcmFsIHZpZXcgb2Ygcmh5dGhtaWMgZ2VuZXMgYWNyb3BoYXNlcwoKYGBge3IgZ2VuZXNfYWNyb3BoYXNlcywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NSwgb3V0LndpZHRoPSI5MCUiLCBmaWcuY2FwPSJBY3JvcGhhc2VzIGRpc3RyaWJ1dGlvbi4ifQpnZ3Bsb3QoZGF0YSA9IGZpbmFsX2RhdGEsIG1hcHBpbmcgPSBhZXMoeD1DUy5hY3JvcGhhc2UsIGZpbGw9ZW5jb2RlZCkpKwogICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSBDUy5hY3JvcGhhc2UsIHkgPSAuLmRlbnNpdHkuLiksIGJpbndpZHRoID0gMC41KSArCiAgICBmYWNldF93cmFwKH5lbmNvZGVkKSArCiAgICBsYWJzKCB4ID0gIkFjcm9waGFzZSIsIHkgPSAiR2VuZXMiLAogICAgICAgICAgdGl0bGUgPSJBY3JvcGhhc2VzIGRpc3RyaWJ1dGlvbiBhY2NvcmRpbmcgdG8gZW5jb2RpbmcgZ2Vub21lIiwKICAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjOTllNTVjIiwgIiNlYjk1N2MiLCAiIzBmYzZlMSIpKQoKCgpjKHBhc3RlMCgiQ2hsb3JvcGxhc3QiLCAiICgiLCBucm93KGZpbmFsX2RhdGFbZmluYWxfZGF0YSRzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJDaGxvcm9wbGFzdCIsXSksICIpIiksCiAgcGFzdGUwKCJDaHJvbW9zb21lIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hyb21vc29tZSIsXSksICIpIiksCiAgcGFzdGUwKCJDaWxpdW0iLCAiICgiLCBucm93KGZpbmFsX2RhdGFbZmluYWxfZGF0YSRzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJDaWxpdW0iLF0pLCAiKSIpLAogIHBhc3RlMCgiQ3l0b3BsYXNtIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ3l0b3BsYXNtIixdKSwgIikiKSwKICBwYXN0ZTAoIkN5dG9za2VsZXRvbiIsICIgKCIsIG5yb3coZmluYWxfZGF0YVtmaW5hbF9kYXRhJHNpbXBsaWZpZWRfc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIkN5dG9za2VsZXRvbiIsXSksICIpIiksCiAgcGFzdGUwKCJFbmRvcGxhc21pYyByZXRpY3VsdW0iLCAiICgiLCBucm93KGZpbmFsX2RhdGFbZmluYWxfZGF0YSRzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJFbmRvcGxhc21pYyByZXRpY3VsdW0iLF0pLCAiKSIpLAogIHBhc3RlMCgiR29sZ2kgYXBwYXJhdHVzIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiR29sZ2kgYXBwYXJhdHVzIixdKSwgIikiKSwgICAKICBwYXN0ZTAoIk1lbWJyYW5lIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiTWVtYnJhbmUiLF0pLCAiKSIpLAogIHBhc3RlMCgiTWl0b2Nob25kcmlvbiIsICIgKCIsIG5yb3coZmluYWxfZGF0YVtmaW5hbF9kYXRhJHNpbXBsaWZpZWRfc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIk1pdG9jaG9uZHJpb24iLF0pLCAiKSIpLAogIHBhc3RlMCgiTnVjbGV1cyIsICIgKCIsIG5yb3coZmluYWxfZGF0YVtmaW5hbF9kYXRhJHNpbXBsaWZpZWRfc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIk51Y2xldXMiLF0pLCAiKSIpLAogIHBhc3RlMCgiT3RoZXIiLCAiICgiLCBucm93KGZpbmFsX2RhdGFbZmluYWxfZGF0YSRzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJPdGhlciIsXSksICIpIiksCiAgcGFzdGUwKCJ1bmtub3duIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAidW5rbm93biIsXSksICIpIikpIC0+IGxvY2F0aW9ucwogICAKI2ZpbmFsX2RhdGEyIDwtIGZpbHRlcihmaW5hbF9kYXRhLCBzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uICE9ICJ1bmtub3duIikKCmdncGxvdChkYXRhID0gZmluYWxfZGF0YSwgbWFwcGluZyA9IGFlcyh4PUNTLmFjcm9waGFzZSwgZmlsbD1zaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uKSkrCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID0wLCB5bWF4ID0gSW5mLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZ29sZCIsIHhtaW4gPSAxMSwgeG1heCA9IDIzLCB5bWluID0wLCB5bWF4ID0gSW5mLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTAsIHltYXggPSBJbmYsIGFscGhhID0wLjMpKwogICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSBDUy5hY3JvcGhhc2UsIHkgPSAuLmRlbnNpdHkuLiksIGJpbndpZHRoID0gMC4zKSArCiAgICBnZW9tX2xpbmUoc3RhdCA9ICJkZW5zaXR5IiwgYWxwaGE9MC41KSArCiAgICBmYWNldF93cmFwKH5zaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uKSsKICAgIGxhYnMoIHggPSAiQWNyb3BoYXNlIiwgeSA9ICJHZW5lcyIsCiAgICAgICAgICAgIHRpdGxlID0iQWNyb3BoYXNlcyBkaXN0cmlidXRpb24gYWNjb3JkaW5nIHRvIGNlbGx1bGFyIGxvY2F0aW9uIiwKICAgICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSsKICAgIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJDZWxsdWxhciBsb2NhdGlvbiIsIGxhYmVscyA9IGxvY2F0aW9ucykKCmBgYAoKIyMgUHV0YXRpdmUgYW5kIGtub3duIHJlZ3VsYXRvcnMKCmBgYHtyIE9UQUZ9CiMgUmVjb3ZlcmluZyBzb21lIHJoeXRobWljIE9UQUZzCm9wciA8LSBmaW5hbF9kYXRhWyB3aGljaChzdGFydHNXaXRoKGZpbmFsX2RhdGEkZ2VuZV9kZXNjcmlwdGlvbiwgIk9jdG90cmljb1BlcHRpZGUgUmVwZWF0IikpICwgXSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCnBwciA8LSBmaW5hbF9kYXRhWyB3aGljaChzdGFydHNXaXRoKGZpbmFsX2RhdGEkZ2VuZV9kZXNjcmlwdGlvbiwgIlBlbnRhdHJpY29QZXB0aWRlIFJlcGVhdCIpKSAsIF0KdHByIDwtIGZpbmFsX2RhdGFbIHdoaWNoKHN0YXJ0c1dpdGgoZmluYWxfZGF0YSRnZW5lX2Rlc2NyaXB0aW9uLCAiVGV0cmF0cmljb1BlcHRpZGUgUmVwZWF0IikpICwgXQoKb3RhZiA8LSB1bmlvbl9hbGwob3ByLCBwcHIpCm90YWYgPC0gdW5pb25fYWxsKG90YWYsIHRwcikKCiMgQWRkaW5nIGV4cHJlc3Npb24gZGF0YToKY29sdW1ucyA8LSBjb2xuYW1lcyhvdGFmKQpvdGFmIDwtIGxlZnRfam9pbihvdGFmLCBybG9nX2RmKQpjb2xuYW1lcyhvdGFmKSA8LSBtYWtlLnVuaXF1ZShjKGNvbHVtbnMsIHJlcChjKDAsIDIsIDQsIDYsIDgsIDEwLCAxMC41LCAxMSwgMTEuNSwgMTIsIDE0LCAxNiwgMTgsIDIwLCAyMiwgMjQpLCBlYWNoPTMpKSkKCiMgUHJlZGljdGVkIGNobG9yb3BsYXN0IGltcG9ydGVkIE9UQUZzCm11bHRpX290YWZfY2hsb3JvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hsb3JvcGxhc3QiKSxdJGdlbmVfc3ltYm9sKXsKICAgIG90YWZbb3RhZiRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgIG11bHRpX290YWZfY2hsb3JvIDwtIHJiaW5kKG11bHRpX290YWZfY2hsb3JvLCB0bXBfZGYpCn0KCm11bHRpX290YWZfY2hsb3JvIDwtIG11bHRpX290YWZfY2hsb3JvWy0xLF0KCiMgUHJlZGljdGVkIG1pdG9jaG9uZHJpb24gaW1wb3J0ZWQgT1RBRnMKbXVsdGlfb3RhZl9taXRvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiTWl0b2Nob25kcmlvbiIpLF0kZ2VuZV9zeW1ib2wpewogICAgb3RhZltvdGFmJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgdG1wX2RmJGdlbmUgPC0gcHJvdAogICAgbXVsdGlfb3RhZl9taXRvIDwtIHJiaW5kKG11bHRpX290YWZfbWl0bywgdG1wX2RmKQp9CgptdWx0aV9vdGFmX21pdG8gPC0gbXVsdGlfb3RhZl9taXRvWy0xLF0KCmBgYAoKYGBge3Igb3JnYW5lbGxlc19nZW5lc30KCiMgRXh0cmFjdGluZyBvcmdhbmVsbGFyIHJoeXRobWljIGdlbmVzCmNobG9ybyA8LSBmaW5hbF9kYXRhWyB3aGljaChzdGFydHNXaXRoKGZpbmFsX2RhdGEkZ2VuZV9pZCwgIkNyZUNwIikpICwgXQptaXRvIDwtIGZpbmFsX2RhdGFbIHdoaWNoKHN0YXJ0c1dpdGgoZmluYWxfZGF0YSRnZW5lX2lkLCAiQ3JlTXQiKSkgLCBdCgoKIyBBZGRpbmcgZXhwcmVzc2lvbiBkYXRhOgpjb2x1bW5zIDwtIGNvbG5hbWVzKGNobG9ybykKY2hsb3JvIDwtIGxlZnRfam9pbihjaGxvcm8sIHJsb2dfZGYpCmNvbG5hbWVzKGNobG9ybykgPC0gbWFrZS51bmlxdWUoYyhjb2x1bW5zLCByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKSkpCmNobG9ybyRnZW5lX3N5bWJvbCA8LSBtYWtlLnVuaXF1ZShjaGxvcm8kZ2VuZV9zeW1ib2wpCgpjb2x1bW5zIDwtIGNvbG5hbWVzKG1pdG8pCm1pdG8gPC0gbGVmdF9qb2luKG1pdG8sIHJsb2dfZGYpCmNvbG5hbWVzKG1pdG8pIDwtIG1ha2UudW5pcXVlKGMoY29sdW1ucywgcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykpKQoKCiMgQ2hsb3JvcGxhc3QKbXVsdGlfY2hsb3JvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIGNobG9ybyRnZW5lX3N5bWJvbCl7CiAgICBjaGxvcm9bY2hsb3JvJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgdG1wX2RmJGdlbmUgPC0gcHJvdAogICAgbXVsdGlfY2hsb3JvIDwtIHJiaW5kKG11bHRpX2NobG9ybywgdG1wX2RmKQp9CgptdWx0aV9jaGxvcm8gPC0gbXVsdGlfY2hsb3JvWy0xLF0KCgojIE1pdG9jaG9uZHJpb24KbXVsdGlfbWl0byA8LSBkYXRhLmZyYW1lKHRpbWU9MCwgZ2VuZV9leHByZXNzaW9uPTAuMCwgZ2VuZT0iIikKCmZvciAocHJvdCBpbiBtaXRvJGdlbmVfc3ltYm9sKXsKICAgIG1pdG9bbWl0byRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgIG11bHRpX21pdG8gPC0gcmJpbmQobXVsdGlfbWl0bywgdG1wX2RmKQp9CgptdWx0aV9taXRvIDwtIG11bHRpX21pdG9bLTEsXQoKCmBgYAoKYGBge3IgZ2VuZV9leHByZXNzaW9uX21vZGVsX3Bsb3RzLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD01LCBmaWcuY2FwPSJHZW5lIGV4cHJlc3Npb24gbW9kZWxzLiJ9CnBlcmlvZGU9MjQKCmdncGxvdChkYXRhID0gbXVsdGlfb3RhZl9jaGxvcm8sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IlJoeXRobWljIGNobG9yb3BsYXN0IGxvY2FsaXNlZCBPVEFGcywgZXhwcmVzc2lvbiBtb2RlbHM6IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKCgpnZ3Bsb3QoZGF0YSA9IG11bHRpX2NobG9ybywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGxldmVsID0gMC45NSwKICAgICAgICAgICAgICAgIGZvcm11bGEgPSB5IH4gc2luKHggLyBwZXJpb2RlICogMiAqIHBpKSArIGNvcyh4IC8gcGVyaW9kZSAqIDIgKiBwaSksCiAgICAgICAgICAgICAgICBmdWxscmFuZ2UgPSBUUlVFKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBsYWJzKHkgPSAicmxvZyhjb3VudHMpIiwgeCA9ICJUaW1lIChoKSIsCiAgICAgICAgIHRpdGxlID0iUmh5dGhtaWMgY2hsb3JvcGxhc3QgZ2VuZXMsIGV4cHJlc3Npb24gbW9kZWxzOiIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCgoKZ2dwbG90KGRhdGEgPSBtdWx0aV9vdGFmX21pdG8sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IlJoeXRobWljIG1pdG9jaG9uZHJpb24gbG9jYWxpc2VkIE9UQUZzLCBleHByZXNzaW9uIG1vZGVsczoiLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQoKCgpnZ3Bsb3QoZGF0YSA9IG11bHRpX21pdG8sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IlJoeXRobWljIG1pdG9jaG9uZHJpb24gZ2VuZXMsIGV4cHJlc3Npb24gbW9kZWxzOiIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCgpgYGAKCgpUbyBwYWlyIE9UQUZzIGFuZCB0aGVpciBwdXRhdGl2ZSBvcmdhbmVsbGFyIG1STkEgdGFyZ2V0cyB3ZSBtdXN0IGxvb2sgYXQ6IAoKLSBPVEFGcyBhbmQgbVJOQSBsb2NhbGlzZWQgaW4gdGhlIHNhbWUgb3JnYW5lbGxlCgotIFdpdGggYWNyb3BoYXNlcyBvZmZzZXQgYnkgYSBmZXcgaG91cnMuIEZyb20gbVJOQSB0aGUgT1RBRiBtdXN0IGJlIHRyYW5zbGF0ZWQsIHRoZW4gaW1wb3J0ZWQgaW50byB0aGUgb3JnYW5lbGxlIHdoZXJlIGl0IG1pZ2h0IGFjdCBvbiBpdHMgbVJOQSB0YXJnZXQuIEhlcmUgSSB1c2VkIGEgNCBob3VycyBzaGlmdGVkIHBvdGVudGlhbCB3aW5kb3cuCgpgYGB7ciBPVEFGX21STkFfcGFpcnMsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTUsIGZpZy5jYXA9IkNhbmRpZGF0ZSBPVEFGL21STkEgdGFyZ2V0IHBhaXJzLiJ9CmFjcm9fZGF5X2NobG9ybyA8LSBkYXRhLmZyYW1lKHRpbWU9MCwgZ2VuZV9leHByZXNzaW9uPTAuMCwgZ2VuZT0iIikKCmZvciAocHJvdCBpbiBjaGxvcm9bd2hpY2goY2hsb3JvJENTLmFjcm9waGFzZSA8MTUgJiBjaGxvcm8kQ1MuYWNyb3BoYXNlID4xMiApLF0kZ2VuZV9zeW1ib2wpIHsKICAgIGNobG9yb1tjaGxvcm8kZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgICAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgICAgICBhY3JvX2RheV9jaGxvcm8gPC0gcmJpbmQoYWNyb19kYXlfY2hsb3JvLCB0bXBfZGYpCn0KCmFjcm9fZGF5X2NobG9ybyA8LSBhY3JvX2RheV9jaGxvcm9bLTEsXQoKCm90YWZfY2hsb3JvX2Fjcm9fZGF5IDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hsb3JvcGxhc3QiICYgb3RhZiRDUy5hY3JvcGhhc2UgPDExICYgb3RhZiRDUy5hY3JvcGhhc2UgPjgpLF0kZ2VuZV9zeW1ib2wpewogICAgb3RhZltvdGFmJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgdG1wX2RmJGdlbmUgPC0gcHJvdAogICAgb3RhZl9jaGxvcm9fYWNyb19kYXkgPC0gcmJpbmQob3RhZl9jaGxvcm9fYWNyb19kYXksIHRtcF9kZikKfQoKb3RhZl9jaGxvcm9fYWNyb19kYXkgPC0gb3RhZl9jaGxvcm9fYWNyb19kYXlbLTEsXQoKCiMgUGxvdHMgCgpnZ3Bsb3QoZGF0YSA9IG90YWZfY2hsb3JvX2Fjcm9fZGF5LCBtYXBwaW5nID0gYWVzKHg9dGltZSwgeT1nZW5lX2V4cHJlc3Npb24sIGdyb3VwPWdlbmUsIGNvbG9yPWdlbmUpKSArIAogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDAsIHhtYXggPSAxMSwgeW1pbiA9NiwgeW1heCA9IDEzLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZ29sZCIsIHhtaW4gPSAxMSwgeG1heCA9IDIzLCB5bWluID02LCB5bWF4ID0gMTMsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAyMywgeG1heCA9IEluZiwgeW1pbiA9NiwgeW1heCA9IDEzLCBhbHBoYSA9MC4zKSsKICAgIGZhY2V0X3dyYXAofmdlbmUpICsKICAgIHlsaW0oNiwgMTMpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGxldmVsID0gMC45NSwKICAgICAgICAgICAgICAgIGZvcm11bGEgPSB5IH4gc2luKHggLyBwZXJpb2RlICogMiAqIHBpKSArIGNvcyh4IC8gcGVyaW9kZSAqIDIgKiBwaSksCiAgICAgICAgICAgICAgICBmdWxscmFuZ2UgPSBUUlVFKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBsYWJzKHkgPSAicmxvZyhjb3VudHMpIiwgeCA9ICJUaW1lIChoKSIsCiAgICAgICAgIHRpdGxlID0iQ2hsb3JvcGxhc3QgbG9jYXRlZCBPVEFGcywgYWNyb3BoYXNlIGF0IGVuZCBvZiBuaWdodCIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKCmdncGxvdChkYXRhID0gYWNyb19kYXlfY2hsb3JvLCBtYXBwaW5nID0gYWVzKHg9dGltZSwgeT1nZW5lX2V4cHJlc3Npb24sIGdyb3VwPWdlbmUsIGNvbG9yPWdlbmUpKSArIAogICAgeWxpbSgxMCwgMjEpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAwLCB4bWF4ID0gMTEsIHltaW4gPTEwLCB5bWF4ID0gMjEsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTEwLCB5bWF4ID0gMjEsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAyMywgeG1heCA9IEluZiwgeW1pbiA9MTAsIHltYXggPSAyMSwgYWxwaGEgPTAuMykrCiAgICBmYWNldF93cmFwKH5nZW5lKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IkNobG9yb3BsYXN0IG1STkEsIGFjcm9waGFzZSBhdCBkYXduIiwKICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkrCiAgICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkKCmBgYAoKSGVyZSwgd2UgY2FuIGlkZW50aWZ5IGtub3duIE9UQUYvY2hsb3JvcGxhc3QgbVJOQSBwYWlycy90cmlvczoKCi0gTURBMSwgVERBMSBhbmQgX2F0cEFfCgotIE1ESDEgKE1USEkxKSwgX2F0cEhfIGFuZCBfYXRwSV8KCi0gQ0NTMiBhbmQgX2Njc0FfCgotIE1DRzEgYW5kIF9wZXRHXwoKLSBSQUExLCBSQUE4IGFuZCBfcHNiQV8KCkJ1dCBhbHNvIG90aGVyIHBvdGVudGlhbCBPVEFGL21STkEgcGFpcnMhCgojIyBSZWZlcmVuY2VzCgpFYmVyaGFyZCBTLCBMb2lzZWxheSBDLCBEcmFwaWVyIEQsIEJ1amFsZG9uIFMsIEdpcmFyZC1CYXNjb3UgSiwgS3VyYXMgUiwgQ2hvcXVldCBZLCBXb2xsbWFuIEZBLiBEdWFsIGZ1bmN0aW9ucyBvZiB0aGUgbnVjbGV1cy1lbmNvZGVkIGZhY3RvciBUREExIGluIHRyYXBwaW5nIGFuZCB0cmFuc2xhdGlvbiBhY3RpdmF0aW9uIG9mIGF0cEEgdHJhbnNjcmlwdHMgaW4gX0NobGFteWRvbW9uYXMgcmVpbmhhcmR0aWlfIGNobG9yb3BsYXN0cy4gX1BsYW50IEouXyAyMDExIFNlcDs2Nyg2KToxMDU1LTY2LiBkb2k6IDEwLjExMTEvai4xMzY1LTMxM1guMjAxMS4wNDY1Ny54LiBFcHViIDIwMTEgSnVsIDE4LiBQTUlEOiAyMTYyMzk3My4KCldhbmcgRiwgSm9obnNvbiBYLCBDYXZhaXVvbG8gTSwgQm9obmUgQVYsIE5pY2tlbHNlbiBKLCBWYWxsb24gTy4gVHdvIF9DaGxhbXlkb21vbmFzXyBPUFIgcHJvdGVpbnMgc3RhYmlsaXplIGNobG9yb3BsYXN0IG1STkFzIGVuY29kaW5nIHNtYWxsIHN1YnVuaXRzIG9mIHBob3Rvc3lzdGVtIElJIGFuZCBjeXRvY2hyb21lIGI2IGYuIF9QbGFudCBKLl8gMjAxNSBKdW47ODIoNSk6ODYxLTczLiBkb2k6IDEwLjExMTEvdHBqLjEyODU4LiBQTUlEOiAyNTg5ODk4Mi4KCkNsaW5lLCBTLiBHLiwgTGF1Z2hiYXVtLCBJLiBBLiBhbmQgSGFtZWwsIFAuIFAuICgyMDE3KSBDQ1MyLCBhbiBPY3RhdHJpY29wZXB0aWRlLVJlcGVhdCBQcm90ZWluLCBJcyBSZXF1aXJlZCBmb3IgUGxhc3RpZCBDeXRvY2hyb21lIGMgQXNzZW1ibHkgaW4gdGhlIEdyZWVuIEFsZ2EgX0NobGFteWRvbW9uYXMgcmVpbmhhcmR0aWlfLiBfRnJvbnRpZXJzIGluIHBsYW50IHNjaWVuY2VfLCA4LCAxMzA2LiBodHRwczovL2RvaS5vcmcvMTAuMzM4OS9mcGxzLjIwMTcuMDEzMDYKClZpb2xhIFMsIENhdmFpdW9sbyBNLCBEcmFwaWVyIEQsIGV0IGFsLiBNREExLCBhIG51Y2xldXMtZW5jb2RlZCBmYWN0b3IgaW52b2x2ZWQgaW4gdGhlIHN0YWJpbGl6YXRpb24gYW5kIHByb2Nlc3Npbmcgb2YgdGhlIF9hdHBBXyB0cmFuc2NyaXB0IGluIHRoZSBjaGxvcm9wbGFzdCBvZiBfQ2hsYW15ZG9tb25hc18uIF9UaGUgUGxhbnQgSm91cm5hbDogZm9yIENlbGwgYW5kIE1vbGVjdWxhciBCaW9sb2d5Xy4gMjAxOSBKdW47OTgoNik6MTAzMy0xMDQ3LiBET0k6IDEwLjExMTEvdHBqLjE0MzAwLgoKU2hpbi1JY2hpcm8gT3phd2EsIE1hcmluYSBDYXZhaXVvbG8sIERvbWl0aWxsZSBKYXJyaWdlLCBSaWNoYXJkIEt1cmFzLCBNYXJrIFJ1dGdlcnMsIFN0ZXBoYW4gRWJlcmhhcmQsIERvbWluaXF1ZSBEcmFwaWVyLCBGcmFuY2lzLUFuZHLDqSBXb2xsbWFuLCBZdmVzIENob3F1ZXQsIFRoZSBPUFIgUHJvdGVpbiBNVEhJMSBDb250cm9scyB0aGUgRXhwcmVzc2lvbiBvZiBUd28gRGlmZmVyZW50IFN1YnVuaXRzIG9mIEFUUCBTeW50aGFzZSBDRm8gaW4gX0NobGFteWRvbW9uYXMgcmVpbmhhcmR0aWlfLCBfVGhlIFBsYW50IENlbGxfLCBWb2x1bWUgMzIsIElzc3VlIDQsIEFwcmlsIDIwMjAsIFBhZ2VzIDExNznigJMxMjAzLCBodHRwczovL2RvaS5vcmcvMTAuMTEwNS90cGMuMTkuMDA3NzAKCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYAoK